package com.example.dailyrecord.aspect;

import com.example.dailyrecord.annotation.EnableLog;
import com.example.dailyrecord.base.entity.ResultMsg;
import com.example.dailyrecord.service.LogService;
import com.example.dailyrecord.service.UserService;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
@Data
public class LogAspect {
    @Resource
    private LogService logService;
    @Resource
    private UserService userService;

    @Pointcut("execution(public * com.example.dailyrecord.controller..*(..)) ||" +
            " execution(public * com.example.dailyrecord.base.controller.BaseController.*(..))")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object o = null;
        HttpServletRequest request = getRequest(joinPoint);
        String action = null, errorMsg = null;
        boolean log = false;

        try {
            o = joinPoint.proceed();
            Method method = getMethod(joinPoint);
            log = log(method);
            action = getAction(method);
        } catch (Throwable e) {
            errorMsg = e.getMessage();
        }
        if (log) {
            String uri = request.getRequestURI();
            if (!uri.startsWith("/log")) {
                String msg = ((ResultMsg) o).getMsg();
                if (StringUtils.isEmpty(errorMsg)) {
                    errorMsg = msg;
                } else {
                    errorMsg = String.format("%s;%s", msg, errorMsg);
                }
                logService.log(request, action, errorMsg);
            }
        }
        return o;
    }

    private HttpServletRequest getRequest(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        HttpServletRequest request = null;
        if (args != null && args.length > 0) {
            request = (HttpServletRequest) args[0];
        }
        return request;
    }

    /**
     * 请求方法中文注解
     */
    private String getAction(Method method) {
        return method.getAnnotation(ApiOperation.class).value();
    }

    private boolean log(Method method) {
        EnableLog enableLog = method.getAnnotation(EnableLog.class);
        if (enableLog == null) {
            return true;
        }
        return enableLog.log();
    }

    public Method getMethod(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        return joinPoint.getTarget().getClass()
                .getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    }
}
